#include "AbstractScene.h"

AbstractScene::AbstractScene()
{
	//Get instances of manager classes.
	sharedGraphicsInterface = GraphicsInterface::GetInstance();
	sharedCollisionManager = CollisionManager::GetInstance();

	//Init scene title to something dull. 
	sceneTitle = (L"Default Scene Title");

	//Init lastMPos
	lastMPos.x = 0;
	lastMPos.y = 0;

	//Create camera.
	camera = new VirtualCamera();
	//Init camera.
	camera->SetPosition(0.0f, 0.0f, 0.0f);
	camera->SetFrustumProperties(DEFAULT_CAMERA_FRUSTUM_FOVY, 
		sharedGraphicsInterface->ReturnBackBufferAspectRatio(),
		DEFAULT_CAMERA_FRUSTUM_NEARZ, DEFAULT_CAMERA_FRUSTUM_FARZ);
	OnResize();
}

AbstractScene::~AbstractScene()
{
	SafeDelete(camera);
}


void AbstractScene::SetTitle(std::wstring title)
{
	sceneTitle = title;
}

void AbstractScene::ControlCameraTranslationsKeyboard(float delta)
{
	if( GetAsyncKeyState('W') & 0x8000 )
		camera->Walk(10.0f*delta*CAMERA_SPEED_MULTIPLER);

	if( GetAsyncKeyState('S') & 0x8000 )
		camera->Walk(-10.0f*delta*CAMERA_SPEED_MULTIPLER);

	if( GetAsyncKeyState('A') & 0x8000 )
		camera->Strafe(-10.0f*delta*CAMERA_SPEED_MULTIPLER);

	if( GetAsyncKeyState('D') & 0x8000 )
		camera->Strafe(10.0f*delta*CAMERA_SPEED_MULTIPLER);
}


void AbstractScene::ControlCameraRotationsMouse(WPARAM btnState, int x, int y, POINT &lastMousePosition)
{
	if( (btnState & MK_LBUTTON) != 0 )
	{
		// Make each pixel correspond to a quarter of a degree.
		float dx = 0.25f*static_cast<float>(x - lastMousePosition.x);
		float dy = 0.25f*static_cast<float>(y - lastMousePosition.y);

		// Clamp the camera so we can't look inside the player model or behind it.
		// NOTE: Will do this for all camera modes until we find a better solution.
		//if ((camera->GetCameraRotationDegreesPitch() + dy < 30.0f) && (camera->GetCameraRotationDegreesPitch() + dy > 0.0f))
		//{
		//	camera->AddPitch(dy);
		//}
		//else if ((camera->GetCameraRotationDegreesPitch() + dy > 290.0f))
		//{
		//	camera->AddPitch(dy);
		//}

		//Current camera pitch accounting for this frames movement. 
		float camP = camera->GetCameraRotationDegreesPitch() + dy;

		if ( ((camP <= 360.0f && camP >= 330.0f)) || ((camP >= 0.0f) && (camP <= 30.0f)) )
			camera->AddPitch(dy);

		//camera->AddPitch(dy);
		camera->AddYaw(dx);
	} 

	lastMousePosition.x = x;
	lastMousePosition.y = y;
}

//Default functionality for the camera.
void AbstractScene::OnMouseDown(WPARAM btnState, int x, int y, UINT originalMessage)
{
	lastMPos.x = x;
	lastMPos.y = y;
}

void AbstractScene::OnMouseMove(WPARAM btnState, int x, int y)
{
	//Should be handled before UpdateWithDelta() is called 
	//due to our gameloop. Thus, no need to RebuildView()
	//just yet. 
	ControlCameraRotationsMouse(btnState, x, y, lastMPos);
}

void AbstractScene::UpdateWithDelta(float delta)
{
	//Update camera.
	ControlCameraTranslationsKeyboard(delta);

	//Rebuild camera view matrix
	camera->RebuildViewMatrix();
}

void AbstractScene::OnResize()
{
	camera->SetFrustumProperties(DEFAULT_CAMERA_FRUSTUM_FOVY, 
		sharedGraphicsInterface->ReturnBackBufferAspectRatio(),
		DEFAULT_CAMERA_FRUSTUM_NEARZ, DEFAULT_CAMERA_FRUSTUM_FARZ);
	camera->RebuildViewMatrix();
}

void AbstractScene::OnSceneReset()
{}